﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AdminBlazor.Infrastructure.Attributes;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Hosting;
using AdminBlazor.Infrastructure.Enums;

namespace AdminBlazor.Infrastructure.Filters;

/// <summary>
/// 结果格式化过滤器
/// </summary>
public class FormatResultFilter : IAsyncActionFilter
{
    private readonly IWebHostEnvironment _env;
    private readonly ILogger<FormatResultFilter> _logger;

    public FormatResultFilter(IWebHostEnvironment env, ILogger<FormatResultFilter> logger)
    {
        _env = env;
        _logger = logger;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var actionExecutedContext = await next();

        if (context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(NonFormatResultAttribute)))
        {
            return;
        }

        if (actionExecutedContext.Exception != null)
        {
            string message;
            var appException = actionExecutedContext.Exception is AppException;
            if (_env.IsProduction())
            {
                message = appException ? actionExecutedContext.Exception.Message : StatusCodes.Status500InternalServerError.ToDescription();
            }
            else
            {
                message = actionExecutedContext.Exception.Message;
            }

            if (!appException)
            {
                _logger.LogError(actionExecutedContext.Exception, "");
            }

            actionExecutedContext.Result = new InternalServerErrorResult(ResultOutput.NotOk(message), appException);
        }
        else
        {
            IActionResult result = actionExecutedContext.Result;

            var formatResult = result switch
            {
                ViewResult => false,
                PartialViewResult => false,
                ViewComponentResult => false,
                PageResult => false,
                FileResult => false,
                SignInResult => false,
                SignOutResult => false,
                RedirectToPageResult => false,
                RedirectToRouteResult => false,
                RedirectResult => false,
                RedirectToActionResult => false,
                LocalRedirectResult => false,
                ChallengeResult => false,
                ForbidResult => false,
                BadRequestObjectResult => false,
                _ => true,
            };

            if (!formatResult)
            {
                return;
            }

            var data = result switch
            {
                ContentResult contentResult => contentResult.Content,
                ObjectResult objectResult => objectResult.Value,
                JsonResult jsonResult => jsonResult.Value,
                _ => null,
            };

            actionExecutedContext.Result = new JsonResult(new ResultOutput<dynamic>().Ok(data));
        }
    }
}